package com.yida.system.service.impl;

import java.util.List;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yida.common.core.constant.CacheConstants;
import com.yida.common.core.enums.DelFlagEnum;
import com.yida.common.core.enums.LimitTimeTypeEnum;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.DateUtils;
import com.yida.common.redis.service.RedisService;
import com.yida.system.api.domain.SysWhiteList;
import com.yida.system.domain.request.SysBlackListEditRequest;
import com.yida.system.domain.request.SysBlackListSaveRequest;
import com.yida.system.mapper.SysWhiteListMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yida.system.mapper.SysBlackListMapper;
import com.yida.system.api.domain.SysBlackList;
import com.yida.system.service.ISysBlackListService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 系统黑名单Service业务层处理
 * 
 * @author wws
 * @date 2023-03-22
 */
@Service
@RequiredArgsConstructor
public class SysBlackListServiceImpl implements ISysBlackListService 
{

    private final SysBlackListMapper sysBlackListMapper;

    private final SysWhiteListMapper sysWhiteListMapper;

    private final RedisService redisService;

    /**
     * 查询系统黑名单
     * 
     * @param id 系统黑名单主键
     * @return 系统黑名单
     */
    @Override
    public SysBlackList selectSysBlackListById(Long id)
    {
        return sysBlackListMapper.selectSysBlackListById(id);
    }

    /**
     * 查询系统黑名单列表
     * 
     * @param sysBlackList 系统黑名单
     * @return 系统黑名单
     */
    @Override
    public List<SysBlackList> selectSysBlackListList(SysBlackList sysBlackList)
    {
        return sysBlackListMapper.selectSysBlackListList(sysBlackList);
    }

    /**
     * 新增系统黑名单
     * 
     * @param saveRequest 系统黑名单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSysBlackList(SysBlackListSaveRequest saveRequest)
    {
        // 查询该IP地址是否存在
        SysBlackList sysBlackList = getInfoByIpAddress(saveRequest.getIpAddress());
        if (ObjectUtil.isNotEmpty(sysBlackList)) {
            throw new ServiceException("当前IP已存在请勿重复添加");
        }
        // 判断白名单中是否存在
        SysWhiteList sysWhiteList = new SysWhiteList();
        sysWhiteList.setIpAddress(saveRequest.getIpAddress());
        if (ObjectUtil.isNotEmpty(sysWhiteListMapper.selectSysWhiteListList(sysWhiteList))) {
            throw new ServiceException("当前IP地址已存在在白名单中");
        }
        // 拷贝黑名单信息
        sysBlackList = new SysBlackList();
        BeanUtil.copyProperties(saveRequest, sysBlackList);
        // 保存黑名单信息
        int result = sysBlackListMapper.insertSysBlackList(sysBlackList);
        if (1 != result) {
            throw new ServiceException("黑名单保存失败");
        }
        // 加入缓存
        addRedis(sysBlackList);
        return result;
    }

    /**
     * 修改系统黑名单
     * 
     * @param editRequest 系统黑名单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSysBlackList(SysBlackListEditRequest editRequest)
    {
        // 查询黑名单信息
        SysBlackList sysBlackList = sysBlackListMapper.selectSysBlackListById(editRequest.getId());
        if (ObjectUtil.isEmpty(sysBlackList)) {
            throw new ServiceException("未查询到对应黑名单信息");
        }
        // 拷贝黑名单参数
        BeanUtil.copyProperties(editRequest, sysBlackList);
        // 更新黑名单信息
        int result = sysBlackListMapper.updateSysBlackList(sysBlackList);
        if (1 != result) {
            throw new ServiceException("黑名单信息修改失败");
        }
        // 删除缓存
        redisService.deleteObject(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX + sysBlackList.getIpAddress());
        // 加入缓存
        addRedis(sysBlackList);
        return result;
    }

    /**
     * 批量删除系统黑名单
     * 
     * @param ids 需要删除的系统黑名单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSysBlackListByIds(Long[] ids)
    {
        if(ObjectUtil.isEmpty(ids)){
            throw new ServiceException("请选中要删除黑名单记录");
        }
        for (Long id : ids) {
            // 查询黑名单信息
            SysBlackList sysBlackList = sysBlackListMapper.selectSysBlackListById(id);
            if (ObjectUtil.isEmpty(sysBlackList)) {
                throw new ServiceException("未查询到对应黑名单信息");
            }
            // 修改参数
            sysBlackList.setDelFlag(DelFlagEnum.DELETE.getType());
            // 更新黑名单信息
            if (1!= sysBlackListMapper.updateSysBlackList(sysBlackList)) {
                throw new ServiceException("黑名单信息删除失败");
            }
            // 删除缓存
            redisService.deleteObject(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX + sysBlackList.getIpAddress());
        }
        return 1;
    }


    /**
     * 根据IP地址查询黑名单信息
     * @param ipAddress IP地址
     * @return
     */
    private SysBlackList getInfoByIpAddress(String ipAddress) {
        SysBlackList sysBlackList = new SysBlackList();
        sysBlackList.setIpAddress(ipAddress);
        return sysBlackListMapper.selectSysBlackList(sysBlackList);
    }

    /**
     * 存入缓存
     * @param sysBlackList 黑名单
     */
    private void addRedis(SysBlackList sysBlackList) {
        // 根据计时类型加入缓存
        if (LimitTimeTypeEnum.PERMANENT.getType().equals(sysBlackList.getLimitTimeType())) {
            redisService.setCacheObject(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX + sysBlackList.getIpAddress(),
                            sysBlackList.getIpAddress());
        }
        else {
            if (ObjectUtil.isEmpty(sysBlackList.getLimitTime())) {
                throw new ServiceException("禁用时长不能为空");
            }
            redisService.setCacheObject(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX + sysBlackList.getIpAddress(),
                            sysBlackList.getIpAddress(), sysBlackList.getLimitTime().longValue(), TimeUnit.MINUTES);
        }
    }
}
